package com.xsy.camera2.demo

import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.graphics.SurfaceTexture
import android.hardware.camera2.CameraCaptureSession
import android.hardware.camera2.CameraDevice
import android.hardware.camera2.CameraManager
import android.hardware.camera2.CaptureRequest
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.HandlerThread
import android.os.Looper
import android.view.Surface
import android.view.TextureView
import android.widget.Toast
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.xsy.camera2.demo.opengl.DefaultCameraRenderer
import com.xsy.camera2.demo.opengl.TextureViewGLWrapper

class MainActivity : AppCompatActivity() {
    var canOpenCamera = false
    var cameraManager: CameraManager? = null
    var cameraDevice: CameraDevice? = null
    var session: CameraCaptureSession? = null
    var surface: Surface? = null

    lateinit var textureView: TextureView
    var surfaceTexture: SurfaceTexture? = null

    val backgroundThread = HandlerThread("bg")
    lateinit var backgroundHandler: Handler

    lateinit var textureViewGLWrapper: TextureViewGLWrapper

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        textureView = findViewById(R.id.texture_view) as TextureView

        val defaultCameraRenderer = DefaultCameraRenderer(this)

        textureViewGLWrapper = TextureViewGLWrapper(defaultCameraRenderer)
        textureViewGLWrapper.setListener({ texture ->
            surfaceTexture = texture
            openCamera()
        }, Handler(Looper.getMainLooper()))

        backgroundThread.start()
        backgroundHandler = Handler(backgroundThread.looper)

        textureView.surfaceTextureListener = object : TextureView.SurfaceTextureListener {
            override fun onSurfaceTextureAvailable(
                surface: SurfaceTexture,
                width: Int,
                height: Int
            ) {
                textureViewGLWrapper.onSurfaceTextureAvailable(surface, width, height)
            }

            override fun onSurfaceTextureSizeChanged(
                surface: SurfaceTexture,
                width: Int,
                height: Int
            ) {
                textureViewGLWrapper.onSurfaceTextureSizeChanged(surface, width, height)
            }

            override fun onSurfaceTextureUpdated(surface: SurfaceTexture) {
                textureViewGLWrapper.onSurfaceTextureUpdated(surface)
            }

            override fun onSurfaceTextureDestroyed(surface: SurfaceTexture): Boolean {
                textureViewGLWrapper.onSurfaceTextureDestroyed(surface)
                return true
            }
        }


//        if (allPermissionGranted()) {
//            canOpenCamera = true
//            openCamera()
//        } else {
//            ActivityCompat.requestPermissions(this, REQUEST_PERMISSIONS, REQUEST_CODE_PERMISSION)
//        }
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == REQUEST_CODE_PERMISSION) {
            if (allPermissionGranted()) {
                openCamera()
            } else {
                Toast.makeText(this, "Permission not granted by the user", Toast.LENGTH_SHORT)
                    .show()
                ActivityCompat.requestPermissions(
                    this,
                    REQUEST_PERMISSIONS,
                    REQUEST_CODE_PERMISSION
                )
            }
        }
    }


    private fun allPermissionGranted() = REQUEST_PERMISSIONS.all {
        ContextCompat.checkSelfPermission(baseContext, it) == PackageManager.PERMISSION_GRANTED
    }


    override fun onResume() {
        super.onResume()
        openCamera()
    }

    override fun onPause() {
        super.onPause()
        closeCamera()
    }

    private fun openCamera() {
        if (!canOpenCamera) return
        if (!textureView.isAvailable) return
        if (surfaceTexture == null) return
        if (cameraDevice != null) return

        cameraManager = getSystemService(Context.CAMERA_SERVICE) as CameraManager
        if (ActivityCompat.checkSelfPermission(
                this,
                Manifest.permission.CAMERA
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            return
        }
        cameraManager!!.openCamera("0", object : CameraDevice.StateCallback() {
            override fun onOpened(camera: CameraDevice) {
                this@MainActivity.cameraDevice = cameraDevice
                this@MainActivity.surface = Surface(surfaceTexture)
                surfaceTexture?.setDefaultBufferSize(textureView.width, textureView.height)
                val req = camera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)
                req.addTarget(surface!!)

                camera.createCaptureSession(
                    listOf(surface),
                    object : CameraCaptureSession.StateCallback() {
                        override fun onConfigured(session: CameraCaptureSession) {
                            req.set(
                                CaptureRequest.CONTROL_AF_MODE,
                                CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE
                            )
                            req.set(
                                CaptureRequest.CONTROL_AE_MODE,
                                CaptureRequest.CONTROL_AE_MODE_ON
                            )
                            req.set(
                                CaptureRequest.CONTROL_AE_ANTIBANDING_MODE,
                                CaptureRequest.CONTROL_AE_ANTIBANDING_MODE_AUTO
                            )
                            session.setRepeatingRequest(req.build(), null, null)
                            this@MainActivity.session = session
                        }

                        override fun onConfigureFailed(session: CameraCaptureSession) {
                            error("onConfigure Failed")
                        }
                    },
                    null
                )
            }

            override fun onDisconnected(camera: CameraDevice) {
            }

            override fun onError(camera: CameraDevice, error: Int) {
                error("camera open failed")
            }

        }, null)
    }

    private fun closeCamera() {
        session?.close()
        session = null
        cameraDevice?.close()
        cameraDevice = null
        surfaceTexture = null
    }

    companion object {
        private const val TAG = "CameraxDemo"
        private const val REQUEST_CODE_PERMISSION = 0x1
        private val REQUEST_PERMISSIONS = mutableListOf(
            Manifest.permission.CAMERA,
            Manifest.permission.RECORD_AUDIO
        ).apply {
            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
                add(Manifest.permission.WRITE_EXTERNAL_STORAGE)
            }
        }.toTypedArray()
    }
}